
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "fcntl.h"
#include "errno.h"
#include "string.h"
#include "signal.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "sys/ioctl.h"

#define	MAX_LENTH	1500
#define	IP		"127.0.0.1"
#define	PORT		9734


static	int	nqueue = 0;
void	sigio_handler(int signum)
{
	if (signum ==SIGIO)
	{
		nqueue++;
	}
	printf("signum=%d,nqueue=%d\n",signum,nqueue);
	return;
}

static	char	recv_buf[MAX_LENTH];
int	main(int argc, char *argv[])
{
	int sockfd, on=1;
	struct sigaction action;
	sigset_t newmask, oldmask;
	struct	sockaddr_in ser_addr;

	memset(&ser_addr, 0, sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_addr.s_addr = inet_addr(IP);
	ser_addr.sin_port = PORT;
	
	// 创建socket
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == -1)
	{
		perror("Create socket failed");
		exit(EXIT_FAILURE);
	}

	// 绑定IP地址
	if (bind(sockfd, (struct sockaddr *) &ser_addr, sizeof(ser_addr)) == -1)
	{
		perror("Bind socket fasiled");
		exit(EXIT_FAILURE);
	}

	memset(&action, 0, sizeof(action));
	action.sa_handler = sigio_handler;
	action.sa_flags = 0;
	// 安装信号
	sigaction(SIGIO, &action, NULL);
	if (fcntl(sockfd, F_SETOWN, getpid()) == -1)	// 设定socket的拥有者
	{
		perror("Fcntl F_SETOWN");
		exit(EXIT_FAILURE);
	}
	if (ioctl(sockfd, FIOASYNC, &on) == -1)	// 设置socket为信号驱动型
	{
		perror("ioctl FIOASYNC");
		exit(EXIT_FAILURE);
	}
	sigemptyset(&oldmask);
	sigemptyset(&newmask);
	sigaddset(&newmask, SIGIO);
	printf("get ready.\n");

	while (1)
	{
		int	len;
		sigprocmask(SIG_BLOCK, &newmask, &oldmask);// 设置当前进程阻塞的信号
		while (nqueue == 0)
		{
			sigsuspend(&oldmask);	// 等待信号
		}
		memset(recv_buf, '\0', MAX_LENTH);
		len = recv(sockfd, recv_buf, MAX_LENTH, MSG_DONTWAIT);// 非阻塞接收数据
		if (len == -1 && errno == EAGAIN)
		{
			nqueue = 0;
		}
		sigprocmask(SIG_SETMASK, &oldmask, NULL);// 修改进程阻塞的信号
		if (len>0)
		{
			printf("recv %d bytes msg is %s\n",len,recv_buf);
		}
	}
	return 0;
}
